﻿#define _CRT_SECURE_NO_WARNINGS 1;
# include<iostream>
using namespace std;


//double Divide(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//	{
//		string s("Divide by zero condition!");
//		throw s;
//	}
//	else
//	{
//		return ((double)a / (double)b);
//	}
//}
//
//void Func()
//{
//	int len, time;
//	cin >> len >> time;
//    cout << Divide(len, time) << endl;
//}
//
//int main()
//{
//	while (1)
//	{
//		try
//		{
//			Func();
//		}
//		catch (const char* errmsg)
//		{
//			cout << errmsg << endl;
//		}
//	}
//
//	return 0;
//}

# include <assert.h>
namespace xx
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

		const_iterator end() const
		{
			return _str + _size;
		}

		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			cout << "string(char* str)-构造" << endl;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		// 拷贝构造
		string(const string& s)
		{
			cout << "string(const string& s) -- 拷贝构造" << endl;
			reserve(s._capacity);
			for (auto ch : s)
			{
				push_back(ch);
			}
		}

		void swap(string& ss)
		{
			::swap(_str, ss._str);
			::swap(_size, ss._size);
			::swap(_capacity, ss._capacity);
		}

		// 移动构造
		string(string&& s)
		{
			cout << "string(string&& s) -- 移动构造" << endl;
			// 转移掠夺你的资源
			swap(s);
		}

		string& operator=(const string& s)
		{
			cout << "string& operator=(const string& s) -- 拷贝赋值" <<
				endl;
			if (this != &s)
			{
				_str[0] = '\0';
				_size = 0;
				reserve(s._capacity);
				for (auto ch : s)
				{
					push_back(ch);
				}
			}
			return *this;
		}

		// 移动赋值
		string& operator=(string&& s)
		{
			cout << "string& operator=(string&& s) -- 移动赋值" << endl;
			swap(s);
			return *this;
		}

		~string()
		{
			cout << "~string() -- 析构" << endl;
			delete[] _str;
			_str = nullptr;
		}

		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}

		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				if (_str)
				{
					strcpy(tmp, _str);
					delete[] _str;
				}
				_str = tmp;
				_capacity = n;
			}
		}

		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity *
					2;
				reserve(newcapacity);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}

		const char* c_str() const
		{
			return _str;
		}

		size_t size() const
		{
			return _size;
		}
	private:
		char* _str = new char('\0');
		size_t _size = 0;
		size_t _capacity = 0;
	};
}


//double Divide(int a, int b)
//{
//	try
//	{
//		xx::string sx;
//		// 当b == 0时抛出异常
//		if (b == 0)
//		{
//			string s("Divide by zero condition!");
//			throw s;
//		}
//		else
//		{
//			return ((double)a / (double)b);
//		}
//		xx::string s;
//	}
//	catch (int errid)
//	{
//		cout << errid << endl;
//	}
//
//}

//void Func()
//{
//	int len, time;
//	cin >> len >> time;
//	xx::string ss2;
//	try
//	{
//		cout << Divide(len, time) << endl;
//	}
//	catch (const int& errmsg)
//	{
//		cout << errmsg << endl;
//	}
//	xx::string ss;
//}

	//int main()
	//{
	//	while (1)
	//	{
	//		try
	//		{
	//			Func();
	//		}
	//		catch (const int& errmsg)
	//		{
	//			cout << errmsg << endl;
	//		}
	//		catch (...) //  任意类型的异常
	//		{
	//			cout << "未知异常" << endl;
	//		}
	//	}
	//	return 0;
	//}
// 一般大型项目程序才会使用异常，下面我们模拟设计一个服务的几个模块
	// 每个模块的继承都是Exception的派生类，每个模块可以添加自己的数据
	// 最后捕获时，我们捕获基类就可以
#include<thread>

	
	class Exception
	{
	public:
		Exception(const string& errmsg, int id)
			:_errmsg(errmsg)
			, _id(id)
		{}

		virtual string what() const
		{
			return _errmsg;
		}

		int getid() const
		{
			return _id;
		}
	protected:
		string _errmsg;
		int _id;
	};

	class SqlException : public Exception
	{
	public:
		SqlException(const string& errmsg, int id, const string& sql)
			:Exception(errmsg, id)
			, _sql(sql)
		{}

		virtual string what() const
		{
			string str = "SqlException:";
			str += _errmsg;
			str += "->";
			str += _sql;
			return str;
		}
	private:
		const string _sql;
	};

	class CacheException : public Exception
	{
	public:
		CacheException(const string& errmsg, int id)
			:Exception(errmsg, id)
		{}

		virtual string what() const
		{
			string str = "CacheException:";
			str += _errmsg;
			return str;
		}
	};

	class HttpException : public Exception
	{
	public:
		HttpException(const string& errmsg, int id, const string& type)
			:Exception(errmsg, id)
			, _type(type)
		{}

		virtual string what() const
		{
			string str = "HttpException:";
			str += _type;
			str += ":";
			str += _errmsg;
			return str;
		}

	private:
		const string _type;
	};

	void SQLMgr()
	{
		if (rand() % 7 == 0)
		{
			throw SqlException("权限不足", 100, "select * from name = '张三'");
		}
		else
		{
			cout << "SQLMgr 调用成功" << endl;
		}
	}

	void CacheMgr()
	{
		if (rand() % 5 == 0)
		{
			throw CacheException("权限不足", 100);
		}
		else if (rand() % 6 == 0)
		{
			throw CacheException("数据不存在", 101);
		}
		else
		{
			cout << "CacheMgr 调用成功" << endl;
		}

		SQLMgr();
	}

	void HttpServer()
	{
		if (rand() % 3 == 0)
		{
			throw HttpException("请求资源不存在", 100, "get");
		}
		else if (rand() % 4 == 0)
		{
			throw HttpException("权限不足", 101, "post");
		}
		else
		{
			cout << "HttpServer调用成功" << endl;
		}

		CacheMgr();
	}

	//int main()
	//{
	//	srand(time(0));
	//
	//	while (1)
	//	{
	//		this_thread::sleep_for(chrono::seconds(1));
	//
	//		try
	//		{
	//			HttpServer();
	//		}
	//		catch (const Exception& e) // 这里捕获基类，基类对象和派生类对象都可以捕获
	//		{
	//			// 多态调用
	//			cout << e.what() << endl;
	//		}
	//		catch (...)
	//		{
	//			cout << "Unkown Exception" << endl;
	//		}
	//	}
	//	return 0;
	//}

	void _SendMsg(const string& s)
	{
		if (rand() % 2 == 0)
		{
			throw HttpException("网络不稳定，发送失败", 102, "put");
		}
		else if (rand() % 7 == 0)
		{
			throw HttpException("你已经不是对象的好友，发送失败", 103, "put");
		}
		else
		{
			cout << "发送成功" << endl;
		}
	}
	void SendMsg(const string& s)
	{
		// 发送消息失败，则再重试3次
		for (size_t i = 0; i < 4; i++)
		{
			try
			{
				_SendMsg(s);
				break;
			}
			catch (const Exception& e)
			{
				// 捕获异常，if中是102号错误，网络不稳定，则重新发送
				// 捕获异常，else中不是102号错误，则将异常重新抛出
				if (e.getid() == 102)
				{
					// 重试三次以后否失败了，则说明网络太差了，重新抛出异常
					if (i == 3)
						throw;

					cout << "开始第" << i + 1 << "重试" << endl;
				}
				else
				{
					// 重新抛出
					throw;
				}
			}
		}
	}

	/*int main()
	{
		srand(time(0));
		string str;
		while (cin >> str)
		{
			try
			{
				SendMsg(str);
			}
			catch (const Exception& e)
			{
				cout << e.what() << endl << endl;
			}
			catch (...)
			{
				cout << "Unkown Exception" << endl;
			}
		}
	
		return 0;
	}*/


	//double Divide(int a, int b)
	//{
	//	// b == 0时抛出异常
	//	if (b == 0)
	//	{
	//		throw "Division by zero condition!";
	//	}
	//	return (double)a / (double)b;
	//}
	//void Func()
	//{
	//	int* array = new int[10];
	//	try
	//	{
	//		int len, time;
	//		cin >> len >> time;
	//		cout << Divide(len, time) << endl;
	//	}
	//	catch (...)
	//	{
	//		// 捕获异常释放内存

	//		cout << "delete []" << array << endl;
	//		delete[] array;
	//	}
	//}
	//int main()
	//{
	//	try
	//	{
	//		Func();
	//	}
	//	catch (const char* errmsg)
	//	{
	//		cout << errmsg << endl;
	//	}
	//	catch (const exception& e)
	//	{
	//		cout << e.what() << endl;
	//	}
	//	catch (...)
	//	{
	//		cout << "Unkown Exception" << endl;
	//	}
	//	return 0;
	//}

	//int main()
	//{
	//	// C++98
 //      // 这⾥表⽰这个函数只会抛出bad_alloc的异常
	//	void* operator new (std::size_t size) throw (std::bad_alloc);
	//	// 这⾥表⽰这个函数不会抛出异常
	//	void* operator delete (std::size_t size, void* ptr) throw();


	//	return 0;
	//}
	
	double Divide(int a, int b) /*noexcept*/
	{
		// b == 0时抛出异常
			if (b == 0)
			{
				throw "Division by zero condition!";
			}
		return (double)a / (double)b;
	}
	int main()
	{
		/*try
		{
			int len, time;
			cin >> len >> time;
			cout << Divide(len, time) << endl;
		}
		catch (const char* errmsg)
		{
			cout << errmsg << endl;
		}
		catch (...)
		{
			cout << "Unkown Exception" << endl;
		}*/
		int i = 0;
		cout << noexcept(Divide(1, 2)) << endl;
		cout << noexcept(Divide(10, 0)) << endl;
		cout << noexcept(++i) << endl;
		return 0;
	}